package com.hrg.demo.service;

import com.hrg.demo.config.FileCleanupProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;

/**
 * @author shenzq
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class FileCleanupService {

    @Value("${images.param.image-base-dir}")
    private String imageBaseDir;


    private final FileCleanupProperties cleanupProperties;

    /**
     * 执行文件清理任务
     */
    public void cleanupFiles() {
        if (!cleanupProperties.isEnabled()) {
            log.info("文件清理功能已禁用");
            return;
        }

        log.info("开始执行文件清理任务...");
        log.info("目标目录: {}", imageBaseDir);
        log.info("清理条件: 文件名长度 > {}, 创建时间超过 {} 天",
                cleanupProperties.getFilenameLength(), cleanupProperties.getExpireDays());

        try {
            List<File> deletedFiles = findAndDeleteExpiredFiles();

            log.info("文件清理完成，共删除 {} 个文件", deletedFiles.size());
            if (!deletedFiles.isEmpty()) {
                log.info("删除的文件列表:");
                deletedFiles.forEach(file ->
                        log.info(" - {} (大小: {} KB)", file.getName(), file.length() / 1024)
                );
            }

        } catch (Exception e) {
            log.error("文件清理任务执行失败", e);
        }
    }

    /**
     * 查找并删除过期文件
     */
    private List<File> findAndDeleteExpiredFiles() throws IOException {
        List<File> deletedFiles = new ArrayList<>();
        Path basePath = Paths.get(imageBaseDir);

        if (!Files.exists(basePath)) {
            log.warn("目标目录不存在: {}", imageBaseDir);
            return deletedFiles;
        }

        Files.walkFileTree(basePath, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                try {
                    if (shouldDelete(file.toFile(), attrs)) {
                        boolean deleted = Files.deleteIfExists(file);
                        if (deleted) {
                            deletedFiles.add(file.toFile());
                            log.debug("已删除文件: {}", file.getFileName());
                        }
                    }
                } catch (Exception e) {
                    log.error("处理文件失败: {}", file, e);
                }
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFileFailed(Path file, IOException exc) {
                log.error("访问文件失败: {}", file, exc);
                return FileVisitResult.CONTINUE;
            }
        });

        return deletedFiles;
    }

    /**
     * 判断文件是否应该删除
     */
    private boolean shouldDelete(File file, BasicFileAttributes attrs) {
        // 检查文件名长度
        String fileName = file.getName();
        boolean isLongName = fileName.length() > cleanupProperties.getFilenameLength();

        // 检查文件创建时间
        boolean isExpired = isFileExpired(attrs);

        // 同时满足两个条件才删除
        boolean shouldDelete = isLongName && isExpired;

        if (shouldDelete) {
            log.debug("符合删除条件: {} (长度: {}, 创建时间: {})",
                    fileName, fileName.length(), getFileCreationTime(attrs));
        }

        return shouldDelete;
    }

    /**
     * 检查文件是否过期
     */
    private boolean isFileExpired(BasicFileAttributes attrs) {
        try {
            Instant creationInstant = attrs.creationTime().toInstant();
            Instant expireInstant = Instant.now()
                    .minusSeconds(cleanupProperties.getExpireDays() * 24L * 60 * 60);

            return creationInstant.isBefore(expireInstant);
        } catch (Exception e) {
            log.warn("无法获取文件创建时间，使用最后修改时间代替");
            // 如果无法获取创建时间，使用最后修改时间作为备选
            Instant modifyInstant = attrs.lastModifiedTime().toInstant();
            Instant expireInstant = Instant.now()
                    .minusSeconds(cleanupProperties.getExpireDays() * 24L * 60 * 60);

            return modifyInstant.isBefore(expireInstant);
        }
    }

    /**
     * 获取文件创建时间的可读格式
     */
    private String getFileCreationTime(BasicFileAttributes attrs) {
        try {
            Instant creationInstant = attrs.creationTime().toInstant();
            return LocalDateTime.ofInstant(creationInstant, ZoneId.systemDefault())
                    .toString();
        } catch (Exception e) {
            return "未知";
        }
    }

    /**
     * 手动触发清理（用于测试）
     */
    public void manualCleanup() {
        log.info("手动触发文件清理");
        cleanupFiles();
    }

    /**
     * 获取目录统计信息
     */
    public void printDirectoryStats() {
        try {
            Path basePath = Paths.get(imageBaseDir);
            if (!Files.exists(basePath)) {
                log.warn("目录不存在: {}", imageBaseDir);
                return;
            }

            DirectoryStats stats = new DirectoryStats();
            Files.walkFileTree(basePath, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                    stats.totalFiles++;
                    stats.totalSize += attrs.size();

                    String fileName = file.getFileName().toString();
                    if (fileName.length() > cleanupProperties.getFilenameLength()) {
                        stats.longNameFiles++;
                    }

                    if (isFileExpired(attrs)) {
                        stats.expiredFiles++;
                    }

                    if (shouldDelete(file.toFile(), attrs)) {
                        stats.toDeleteFiles++;
                    }

                    return FileVisitResult.CONTINUE;
                }
            });

            log.info("=== 目录统计信息 ===");
            log.info("总文件数: {}", stats.totalFiles);
            log.info("总大小: {} MB", stats.totalSize / 1024 / 1024);
            log.info("长文件名文件数: {}", stats.longNameFiles);
            log.info("过期文件数: {}", stats.expiredFiles);
            log.info("符合删除条件的文件数: {}", stats.toDeleteFiles);

        } catch (Exception e) {
            log.error("获取目录统计信息失败", e);
        }
    }

    private static class DirectoryStats {
        int totalFiles = 0;
        long totalSize = 0;
        int longNameFiles = 0;
        int expiredFiles = 0;
        int toDeleteFiles = 0;
    }
}
